package main

import (
	"strconv"
	"strings"
)

// 包含32个元素。这个数组可能用于表示某种开关状态或标志位的集合，每个元素的值为0或1，通常在编程中用来表示“关闭”或“开启”状态
var prtsw = [32]int{0, 1, 0, 1, 0, 0, 1, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	1, 0, 1, 0, 1, 0, 1, 0}

var blank = "     "

// prreset 函数用于重置 prtsw 数组，并设置特定位置的值为 1。
func prreset() {
    // 将 prtsw 数组的所有元素初始化为 0
    for i := 0; i < 32; i++ {
        prtsw[i] = 0
    }

    // 设置特定位置的值为 1
    prtsw[1] = 1
    prtsw[3] = 1
    prtsw[6] = 1
    prtsw[24] = 1
    prtsw[26] = 1
    prtsw[28] = 1
    prtsw[30] = 1
}

// doprint 函数生成打印输出字符串。
func doprint() (s string) {
    var raw [9]string      // 存储原始数据的数组
    var sgn [16]byte       // 存储符号信息的数组

    // 获取主处理器状态并存储在 raw[0]
    raw[0] = mpstat()

    // 获取累加器状态并存储在 raw[1] 到 raw[8]
    for i := 1; i < 9; i++ {
        raw[i] = accstat(i + 11)
    }

    // 初始化 p1 字符串，从 raw[0] 中提取部分数据
    p1 := raw[0][13:18]

    // 设置 sgn 数组的第一个符号为 'P'
    sgn[0] = 'P'

    // 将 raw[1] 的部分数据追加到 p1，并设置相应的符号
    p1 += raw[1][2:12]
    sgn[1] = raw[1][0]
    sgn[2] = raw[1][0]

    // 将 raw[2] 的部分数据追加到 p1，并设置相应的符号
    p1 += raw[2][2:12]
    sgn[3] = raw[2][0]
    sgn[4] = raw[2][0]

    // 将 raw[3] 的部分数据追加到 p1，并设置相应的符号
    p1 += raw[3][7:12]
    sgn[5] = raw[3][0]

    // 将 raw[4] 到 raw[8] 的部分数据追加到 p1，并设置相应的符号
    for i := 4; i < 9; i++ {
        p1 += raw[i][2:12]
        sgn[2*(i-4)+6] = raw[i][0]
        sgn[2*(i-4)+7] = raw[i][0]
    }

    // 初始化 p2 字符串和相关的索引变量
    p2 := ""
    st := 0
    ed := 0
    comb := 0

    // 根据 prtsw 数组的状态和符号信息生成 p2 字符串
    for fld := 0; fld < 16; fld++ {
        if comb == 8 {
            comb = 24
        }
        if prtsw[comb] == 0 || fld == 15 {
            ed = (fld + 1) * 5
            if sgn[fld] == 'P' {
                p2 += p1[st:ed]
            } else {
                p2 += sm2tenc(p1[st:ed])
            }
            st = ed
        }
        comb++
    }

    // 根据 prtsw 数组的状态生成最终的输出字符串 s
    s = ""
    for fld := 0; fld < 16; fld++ {
        if prtsw[fld+8] == 0 {
            s += blank // 假设 blank 是一个预定义的空白字符或字符串
        } else {
            s += p2[5*fld : 5*(fld+1)]
        }
    }

    return s
}

// sm2tenc 函数将一个字符串 s 转换为十进制表示形式。
func sm2tenc(s string) string {
    var nz int // 用于记录非零字符的位置

    l := len(s) // 获取字符串 s 的长度

    // 找到从右向左第一个非零字符的位置
    for nz = l - 1; nz >= 0 && s[nz] == '0'; nz-- {
    }

    if nz < 0 { // 如果整个字符串都是 '0'
        return s // 返回原字符串
    } else if nz == 0 { // 特殊情况：处理 10 进制补码和 11-punch
        // 根据特定规则转换第一个字符，并保持后续字符不变
        return string('9'+1-s[0]-1+'J') + s[1:]
    } else {
        // 根据特定规则转换第一个字符
        sc := string('9' - s[0] - 1 + 'J')
        if sc == "I" { // 特殊情况：如果转换后的字符是 "I"，则替换为 "-"
            sc = "-"
        }
        // 转换中间部分的字符
        for i := 1; i < nz; i++ {
            sc += string('9' - s[i] + '0')
        }
        // 转换最后一个非零字符
        sc += string('9' + 1 - s[nz] + '0')
        // 保持剩余部分不变
        sc += s[nz+1:]
        return sc
    }
}

// prctl 函数通过通道 ch 接收控制指令，并根据指令更新 prtsw 数组的状态。
func prctl(ch chan [2]string) {
    for {
        ctl := <-ch // 从通道中接收控制指令
        n := strings.IndexRune(ctl[0], '-') // 查找 ctl[0] 中的第一个 '-' 字符位置

        if n == -1 { // 如果没有找到 '-'
            sw, _ := strconv.Atoi(ctl[0]) // 将 ctl[0] 转换为整数
            // 根据 ctl[1] 的值设置 prtsw 数组中的相应位置
            if ctl[1][0] == 'p' || ctl[1][0] == 'P' {
                prtsw[sw+7] = 1
            } else {
                prtsw[sw+7] = 0
            }
        } else { // 如果找到了 '-'
            sw, _ := strconv.Atoi(ctl[0][:n]) // 提取 ctl[0] 中 '-' 之前的数字
            offset := 0
            if sw >= 9 {
                offset = 16 // 如果 sw 大于等于 9，则偏移量为 16
            }
            // 根据 ctl[1] 的值设置 prtsw 数组中的相应位置
            if ctl[1] == "c" || ctl[1] == "C" {
                prtsw[sw-1+offset] = 1
            } else {
                prtsw[sw-1+offset] = 0
            }
        }
    }
}
